package com.realestate.controller;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.mail.MailException;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import com.realestate.common.RealEstateMail;
import com.realestate.constants.AppConstant;
import com.realestate.model.BrtbBuilding;
import com.realestate.model.BrtbDistrict;
import com.realestate.model.BrtbProduct;
import com.realestate.model.BrtbProductCommonAttrValue;
import com.realestate.services.BuildingService;
import com.realestate.services.DistrictService;
import com.realestate.services.ProductCommonAttributeValueService;
import com.realestate.services.ProductQueryService;

@Controller
public class InitController {
	@Autowired
	private ProductQueryService productService;

	@Autowired
	private ProductCommonAttributeValueService commonAttributeService;
	
	@Autowired
	private RealEstateMail realEstateMail;
	
	@Autowired
	private BuildingService buildingService;
	
	@Autowired
	private DistrictService districtService;
	
	@RequestMapping(value = "/", method = RequestMethod.GET)
	public ModelAndView getdata() {
		// load data for search form
		// load buildings and districts
		List<BrtbBuilding> buildings = buildingService.getAllBuilding();
		List<BrtbDistrict> districts = districtService.getAllDistricts();
		
		// load data for index page
		List<BrtbProduct> listNewProperty = productService
				.getListproductByCategoryCode(AppConstant.ALL,
						AppConstant.LIMIT, null, null);
		List<BrtbProduct> listApartments = productService
				.getListproductByCategoryCode(AppConstant.APARTMENT,
						AppConstant.LIMIT, null, null);
		List<BrtbProduct> listHouses = productService
				.getListproductByCategoryCode(AppConstant.HOUSE,
						AppConstant.LIMIT, null, null);
		List<BrtbProduct> listVillas = productService
				.getListproductByCategoryCode(AppConstant.VILLA,
						AppConstant.LIMIT, null, null);
		List<BrtbProduct> listSApartments = productService
				.getListproductByCategoryCode(AppConstant.SERVICED_APARTMENT,
						AppConstant.LIMIT, null, null);
		List<BrtbProduct> listResorts = productService
				.getListproductByCategoryCode(AppConstant.RESORT,
						AppConstant.LIMIT, null, null);

		ModelAndView model = new ModelAndView("index");

		// add data to model
		model.addObject("listNewProperty", listNewProperty);
		model.addObject("listApartments", listApartments);
		model.addObject("listHouses", listHouses);
		model.addObject("listVillas", listVillas);
		model.addObject("listSApartments", listSApartments);
		model.addObject("listResorts", listResorts);

		// add buildings and districts to model
		model.addObject("buildings", buildings);
		model.addObject("districts", districts);
		
		return model;
	}

	@RequestMapping("/resultProperty")
	public ModelAndView resultProperty(
			@RequestParam(value = "buildingCode", required = false) String buildingCode,
			@RequestParam(value = "categoryCode", required = false) String categoryCode,
			@RequestParam(value = "districtCode", required = false) String districtCode,
			@RequestParam(value = "pageSize", required = false) String pageSize,
			@RequestParam(value = "page", required = false) String page) {
		// return newest property
		List<BrtbProduct> listNewProperty = productService
				.getListproductByCategoryCode(AppConstant.ALL,
						AppConstant.LIMIT, null, null);
		
		ModelAndView result = new ModelAndView("resultProperty"); 
		Integer pageSizeNumber = AppConstant.PAGE_SIZE;
		Integer pageNumber = 1;
		if(pageSize != null){
			pageSizeNumber = Integer.parseInt(pageSize);
		}
		if(page != null){
			 pageNumber = Integer.parseInt(page);
		}
	    Pageable pageable = new PageRequest(pageNumber-1, pageSizeNumber);
	    Page<BrtbProduct> products;
	    if(districtCode != null){
	    	products = productService.getPagingProduct(pageable, categoryCode, districtCode, buildingCode);
		}else{
			products = productService.getPagingProduct(pageable, categoryCode);
		}
	    
	    result.addObject("products", products);
	    
	    int current = products.getNumber() + 1;
	    int begin = Math.max(1, current - 5);
	    int end = Math.min(begin + 10, products.getTotalPages());
	    
	    result.addObject("beginIndex", begin);
	    result.addObject("endIndex", end);
	    result.addObject("currentIndex", current);
	    result.addObject("categoryCode", categoryCode);
	    // add newest property for result
	    result.addObject("listNewProperty", listNewProperty);
		return result; 
	}
	
	/**
	 * Simple search
	 * @param request
	 * @return
	 */
	@RequestMapping(value = "/searchProperty", method = RequestMethod.GET)
	public ModelAndView searchProperty(HttpServletRequest request){
		// return newest property
		List<BrtbProduct> listNewProperty = productService
				.getListproductByCategoryCode(AppConstant.ALL,
						AppConstant.LIMIT, null, null);
				
		Map<String, String> attributes = new HashMap<String, String>();
		if(!"".equals(request.getParameter("keyword"))){
			attributes.put(AppConstant.PRODUCTNAME, request.getParameter("keyword"));
		}
		if(!"".equals(request.getParameter(AppConstant.BUILDING))){
			attributes.put(AppConstant.BUILDING, request.getParameter(AppConstant.BUILDING));
		}
		if(!"".equals(request.getParameter(AppConstant.RENT))){
			attributes.put(AppConstant.RENT, request.getParameter(AppConstant.RENT));
		}
		if(!"".equals(request.getParameter(AppConstant.SALE))){
			attributes.put(AppConstant.SALE, request.getParameter(AppConstant.SALE));
		}
		if(!"".equals(request.getParameter(AppConstant.APARTMENT))){
			attributes.put(AppConstant.APARTMENT, request.getParameter(AppConstant.APARTMENT));
		}
		if(!"".equals(request.getParameter(AppConstant.HOUSE))){
			attributes.put(AppConstant.HOUSE, request.getParameter(AppConstant.HOUSE));
		}
		if(!"".equals(request.getParameter(AppConstant.VILLA))){
			attributes.put(AppConstant.VILLA, request.getParameter(AppConstant.VILLA));
		}
		if(!"".equals(request.getParameter(AppConstant.RESORT))){
			attributes.put(AppConstant.RESORT, request.getParameter(AppConstant.RESORT));
		}
		if(!"".equals(request.getParameter(AppConstant.SERVICED_APARTMENT))){
			attributes.put(AppConstant.SERVICED_APARTMENT, request.getParameter(AppConstant.SERVICED_APARTMENT));
		}
		if(!"".equals(request.getParameter(AppConstant.DISTRICT))){
			attributes.put(AppConstant.DISTRICT, request.getParameter(AppConstant.DISTRICT));
		}
		if(!"".equals(request.getParameter(AppConstant.BEDROOM))){
			attributes.put(AppConstant.BEDROOM, request.getParameter(AppConstant.BEDROOM));
		}
		if(!"".equals(request.getParameter(AppConstant.PRICE))){
			attributes.put(AppConstant.PRICE, request.getParameter(AppConstant.PRICE));
		}
		
		ModelAndView result = new ModelAndView("resultProperty"); 
		
		// Pageable
		Integer pageSizeNumber = 10;
		Integer pageNumber = 1;
		
	    Pageable pageable = new PageRequest(pageNumber-1, pageSizeNumber);
	    Page<BrtbProduct> products = productService.getPagingProductSimpleSearch(pageable, attributes);
	   
	    result.addObject("products", products);
	    
	    int current = products.getNumber() + 1;
	    int begin = Math.max(1, current - 5);
	    int end = Math.min(begin + 10, products.getTotalPages());
	    
	    result.addObject("beginIndex", begin);
	    result.addObject("endIndex", end);
	    result.addObject("currentIndex", current);
	    
	    // add hot property
	    result.addObject("listNewProperty", listNewProperty);
		return result; 
	}
	
	@RequestMapping("/productDetail/{productId}")
	public ModelAndView productDetail(@PathVariable Long productId) {
		BrtbProduct product = productService.findProductById(productId);
		ModelAndView modelAndView = new ModelAndView("productDetail");
		modelAndView.addObject("product", product);
		// get amenities of product
		modelAndView.addObject("amenities", commonAttributeService
				.getAllCommonAttributesOfAProduct(productId));
		// get 6 product has the same category
		modelAndView.addObject("relateProducts", productService
				.getListproductByCategoryCode(product.getBrtbCategory()
						.getCategoryCode(), AppConstant.LIMIT, product.getId(),
						product.getTypeProduct()));
		return modelAndView;
	}

	@RequestMapping("/advancedSearch")
	public ModelAndView advancedSearch() {
		return new ModelAndView("advancedSearch");
	}

	@RequestMapping(value ="/compareProducts", method = RequestMethod.GET)
	public ModelAndView compareProducts(HttpServletRequest request) {
		ModelAndView result = new ModelAndView("compareProducts");
		String productId0 = request.getParameter("id0");
		String productId1 = request.getParameter("id1");
		String productId2 = request.getParameter("id2");
		BrtbProduct product0 = null;
		BrtbProduct product1 = null;
		BrtbProduct product2 = null;
		Map<String, Boolean> productCommonValue0;
		Map<String, Boolean> productCommonValue1;
		Map<String, Boolean> productCommonValue2;

		if(productId0 != null){
			product0 = productService.findProductById(Long.parseLong(productId0));
			List<BrtbProductCommonAttrValue> listProduct0 = commonAttributeService.getAllCommonAttributesOfAProduct(product0.getId());
			productCommonValue0 = getCommonAttributeValue(listProduct0);
			result.addObject("product0", product0);
			result.addObject("listProduct0", listProduct0);
			result.addObject("productCommonValue0", productCommonValue0);
		}
		if(productId1 != null){
			product1 = productService.findProductById(Long.parseLong(productId1));
			List<BrtbProductCommonAttrValue> listProduct1 = commonAttributeService.getAllCommonAttributesOfAProduct(product1.getId());
			productCommonValue1 = getCommonAttributeValue(listProduct1);
			result.addObject("product1", product1);
			result.addObject("listProduct1", listProduct1);
			result.addObject("productCommonValue1", productCommonValue1);
		}
		if(productId2 != null){
			product2 = productService.findProductById(Long.parseLong(productId2));
			List<BrtbProductCommonAttrValue> listProduct2 = commonAttributeService.getAllCommonAttributesOfAProduct(product2.getId());
			productCommonValue2 = getCommonAttributeValue(listProduct2);
			result.addObject("product2", product2);
			result.addObject("listProduct2", listProduct2);
			result.addObject("productCommonValue2", productCommonValue2);
		}
		Integer minPrice = 0;
		Integer minSqft = 0;
		Integer minRoom = 0;
		Integer minBedRoom = 0;
		// compare price
		if(product0 != null && product1 != null && product2 != null ){
			minPrice = minValue(product0.getPrice(), product1.getPrice(), product2.getPrice());
			minSqft = maxValue(product0.getSqft(), product1.getSqft(), product2.getSqft());
			minRoom = maxValue(product0.getRoom(), product1.getRoom(), product2.getRoom());
			minBedRoom = maxValue(product0.getBedroom(), product1.getBedroom(), product2.getBedroom());
		}
		if(product0 != null && product1 != null){
			minPrice = minValue(product0.getPrice(), product1.getPrice());
			minSqft = maxValue(product0.getSqft(), product1.getSqft());
			minRoom = maxValue(product0.getRoom(), product1.getRoom());
			minBedRoom = maxValue(product0.getBedroom(), product1.getBedroom());
		}
		result.addObject("minPrice", minPrice);
		result.addObject("minSqft", minSqft);
		result.addObject("minRoom", minRoom);
		result.addObject("minBedRoom", minBedRoom);
		
		// related product => newest products
		List<BrtbProduct> listNewProperty = productService
				.getListproductByCategoryCode(AppConstant.ALL,
						AppConstant.LIMIT, null, null);
		// add newest property for result
	    result.addObject("listNewProperty", listNewProperty);
	    
		return result;
	}

	@RequestMapping("/sendenquiry")
	public @ResponseBody String sendEnquiry(@RequestParam(value="name", required=true) String name,
			@RequestParam(value="email", required=true) String email,
			@RequestParam(value="contactNumber", required=true) String contactNumber,
			@RequestParam(value="enquiry", required=true) String enquiry) {
		StringBuffer content = new StringBuffer();
		try{
			content.append("Name's customer: ").append(name).append("\n");
			content.append("Her/his email: ").append(email).append("\n");
			content.append("Her/his phone number: ").append(contactNumber).append("\n");
			content.append("The main content: ").append(enquiry);
			realEstateMail.sendMail("Business staff", content.toString());
		}catch(MailException ex){
			return AppConstant.FAIL;
		}
		return AppConstant.SUCCESS;
	}
	
	private Integer minValue(Integer... values){
		Integer min = values[0];
		if(values.length > 0){
			for(int i = 1; i < values.length; i++){
				if(values[i] < min){
					min = values[i];
				}
			}
		}
		return min;
	}
	
	private Integer maxValue(Integer... values){
		Integer max = values[0];
		if(values.length > 0){
			for(int i = 1; i < values.length; i++){
				if(values[i] > max){
					max = values[i];
				}
			}
		}
		return max;
	}
	private Map<String, Boolean> getCommonAttributeValue(List<BrtbProductCommonAttrValue> values){
		Map<String, Boolean> productCommonValue = new HashMap<String, Boolean>();
		for(BrtbProductCommonAttrValue att : values){
			if(att.getBrtbCommonAttribute().getCommonAttributeCode().equals(AppConstant.INTERNET)
					|| att.getBrtbCommonAttribute().getCommonAttributeCode().equals(AppConstant.BALCONY)
					|| att.getBrtbCommonAttribute().getCommonAttributeCode().equals(AppConstant.HOSPITAL)
					|| att.getBrtbCommonAttribute().getCommonAttributeCode().equals(AppConstant.PARKING)
					|| att.getBrtbCommonAttribute().getCommonAttributeCode().equals(AppConstant.GARDEN)
					|| att.getBrtbCommonAttribute().getCommonAttributeCode().equals(AppConstant.BASEMENT)
					|| att.getBrtbCommonAttribute().getCommonAttributeCode().equals(AppConstant.SHOPPING_CENTER)
					|| att.getBrtbCommonAttribute().getCommonAttributeCode().equals(AppConstant.SECURITY)
					|| att.getBrtbCommonAttribute().getCommonAttributeCode().equals(AppConstant.FRONTYARD)
					|| att.getBrtbCommonAttribute().getCommonAttributeCode().equals(AppConstant.TERRACE)){
				productCommonValue.put(att.getBrtbCommonAttribute().getCommonAttributeCode(), Boolean.valueOf("true"));
			}
		}
		return productCommonValue;
	}
	
	@RequestMapping("/session")
	public ModelAndView session() {
		return new ModelAndView("session");
	}
	
	@RequestMapping("/asyncSessionVariable")
	public @ResponseBody String asyncSessionVariable(HttpServletRequest request) {
		Map<String, String[]> maps = request.getParameterMap();
		Set<String> keySet = maps.keySet();
		if(keySet.iterator().hasNext()){
			String key = keySet.iterator().next();
			String[] value = maps.get(key);
			String sessionValue = (String)request.getSession().getAttribute("myFavourites");
			if(sessionValue.length() > 0){
				request.getSession().setAttribute("myFavourites", sessionValue + key + "=" + value[0] + ";");
			}else{
				request.getSession().setAttribute("myFavourites", key + "=" + value[0]+ ";");
			}
			
			return (String)request.getSession().getAttribute("myFavourites");
		}
		return AppConstant.FAIL;
	}
	
	@RequestMapping("/asyncSessionVariableDel")
	public @ResponseBody String asyncSessionVariableDel(HttpServletRequest request) {
		Map<String, String[]> maps = request.getParameterMap();
		String productId = request.getParameter("id");
		if(productId != null){
			String sessionValue = (String)request.getSession().getAttribute("myFavourites");
			String[] sessionPara = sessionValue.split(";");
			for(String param : sessionPara){
				String[] idValue = param.split("=");
				if(idValue.length > 0){
					if(idValue[0].equals(productId)){
						String newSessionValue = sessionValue.replace(param + ";", "");
						request.getSession().setAttribute("myFavourites", newSessionValue);
						break;
					}
				}
			}
			return (String)request.getSession().getAttribute("myFavourites");
		}
		return AppConstant.FAIL;
	}
}
